package com.huishu.coupon.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huishu.commons.config.cache.RedisUtil;
import com.huishu.commons.constant.RedisKeyPrefix;
import com.huishu.commons.exception.BaseException;
import com.huishu.commons.pojo.Result;
import com.huishu.commons.pojo.dto.ReturnUserCouponDTO;
import com.huishu.commons.pojo.dto.UseCouponDTO;
import com.huishu.commons.pojo.model.UserDO;
import com.huishu.commons.utlis.WechatUtil;
import com.huishu.coupon.fegin.UserFeignClient;
import com.huishu.coupon.mapper.CouponHistoryMapper;
import com.huishu.coupon.mapper.CouponMapper;
import com.huishu.coupon.pojo.model.CouponDO;
import com.huishu.coupon.pojo.model.CouponHistoryDO;
import com.huishu.coupon.service.CouponHistoryService;
import com.huishu.coupon.utils.AssistantContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author generator@ljj
 * @since 2023-04-10
 */
@Slf4j
@Service
public class CouponHistoryServiceImpl extends ServiceImpl<CouponHistoryMapper, CouponHistoryDO> implements CouponHistoryService {

    @Autowired
    private CouponMapper couponMapper;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private RedisUtil redisUtil;

    @Transactional
    @Override
    public Result useCoupon(List<UseCouponDTO> useCoupons) {
        for (UseCouponDTO useCouponDTO : useCoupons) {
            LambdaUpdateWrapper<CouponHistoryDO> uw = Wrappers.lambdaUpdate(CouponHistoryDO.class)
                    .set(CouponHistoryDO::getUseStatus, 1)
                    .set(CouponHistoryDO::getOrderId, useCouponDTO.getOrderId())
                    .set(CouponHistoryDO::getOrderSn, useCouponDTO.getOrderSn())
                    .eq(CouponHistoryDO::getUserId, useCouponDTO.getUserId())
                    .eq(CouponHistoryDO::getCouponId, useCouponDTO.getCouponId());
            int update = this.baseMapper.update(null, uw);
            if (update <= 0) {
                throw new BaseException("使用优惠卷失败");
            }
        }
        return Result.success();
    }

    @Override
    public Result myCoupon(Integer type) {
        if (type == 1) {
            // 查询我的优惠卷
            LambdaQueryWrapper<CouponHistoryDO> queryWrapper = Wrappers.lambdaQuery(CouponHistoryDO.class)
                    .eq(CouponHistoryDO::getUserId, AssistantContext.getCurrentUid())
                    .and(QueryWrapper -> QueryWrapper.eq(CouponHistoryDO::getUseStatus, 0).or().eq(CouponHistoryDO::getUseStatus, 3));
            List<CouponHistoryDO> couponHistorys = this.list(queryWrapper);
            if (CollectionUtils.isEmpty(couponHistorys)) {
                return Result.success();
            }
            Map<Long, List<CouponHistoryDO>> collect = couponHistorys.stream().collect(Collectors.groupingBy(CouponHistoryDO::getCouponId));
            List<Long> coupinIds = couponHistorys.stream().map(CouponHistoryDO::getCouponId).collect(Collectors.toList());
            List<CouponDO> couponDOS = couponMapper.selectBatchIds(coupinIds);
            for (CouponDO couponDO : couponDOS) {
                if (couponDO.getType() == 2) {
                    // 处理复购卷时间
                    List<CouponHistoryDO> couponHistoryDOS = collect.get(couponDO.getId());
                    couponDO.setEndDate(couponHistoryDOS.get(0).getOverdueDate());
                }
            }
            return Result.success(couponDOS);
        } else {
            // 查询待领取优惠卷
            LambdaQueryWrapper<CouponHistoryDO> queryWrapper = Wrappers.lambdaQuery(CouponHistoryDO.class)
                    .eq(CouponHistoryDO::getUserId, AssistantContext.getCurrentUid())
                    .eq(CouponHistoryDO::getUseStatus, 0);
            List<CouponHistoryDO> couponHistorys = this.list(queryWrapper);
            if (CollectionUtils.isEmpty(couponHistorys)) {
                LambdaQueryWrapper<CouponDO> couponQueryWrapper = Wrappers.lambdaQuery(CouponDO.class)
                        .le(CouponDO::getStartDate, new Date())
                        .ge(CouponDO::getEndDate, new Date())
                        .eq(CouponDO::getType, 0);
                return Result.success(couponMapper.selectList(couponQueryWrapper));
            }
            List<Long> coupinIds = couponHistorys.stream().map(CouponHistoryDO::getCouponId).collect(Collectors.toList());
            LambdaQueryWrapper<CouponDO> couponQueryWrapper = Wrappers.lambdaQuery(CouponDO.class)
                    .le(CouponDO::getStartDate, new Date())
                    .ge(CouponDO::getEndDate, new Date())
                    .eq(CouponDO::getType, 0)
                    .notIn(CouponDO::getId, coupinIds);
            return Result.success(couponMapper.selectList(couponQueryWrapper));
        }

    }

    @Override
    public Result draw(Long couponId) {
        // 查询是否领取过 默认只能领取1张
        LambdaQueryWrapper<CouponHistoryDO> queryWrapper = Wrappers.lambdaQuery(CouponHistoryDO.class)
                .eq(CouponHistoryDO::getUserId, AssistantContext.getCurrentUid())
                .eq(CouponHistoryDO::getCouponId, couponId);
        CouponHistoryDO couponHistoryDO = getOne(queryWrapper);
        if (couponHistoryDO != null) {
            return Result.fail("您已经领取过该优惠卷了！");
        }
        couponHistoryDO = new CouponHistoryDO();
        couponHistoryDO.setUserId(AssistantContext.getCurrentUid());
        couponHistoryDO.setCouponId(couponId);
        couponHistoryDO.setGetType(1);
        this.save(couponHistoryDO);
        return Result.success();
    }

    @Override
    public Result returnUserCoupon(ReturnUserCouponDTO returnUserCouponDTO) {
        LambdaUpdateWrapper<CouponHistoryDO> uw = Wrappers.lambdaUpdate(CouponHistoryDO.class)
                .set(CouponHistoryDO::getUseStatus, 0)
                .set(CouponHistoryDO::getUseDate, null)
                .set(CouponHistoryDO::getOrderSn, null)
                .set(CouponHistoryDO::getOrderId, null)
                .eq(CouponHistoryDO::getUserId, returnUserCouponDTO.getUserId())
                .in(CouponHistoryDO::getCouponId, returnUserCouponDTO.getCouponIds());
        int update = this.baseMapper.update(null, uw);
        if (update > 0) {
            return Result.success();
        }
        return Result.fail();
    }

    @Override
    public Result receiveAssociation(Long couponId, String code) {
        log.info("领取社群优惠卷 couponId:{},code:{}", couponId, code);
        String openId = WechatUtil.getOpenId(code);
        String hget = redisUtil.hget(RedisKeyPrefix.ASSOCIATION_COUPON + openId, couponId.toString());
        if (hget != null) {
            return Result.fail("您已经领取过该优惠卷了！");
        }
        // 根据openId获取用户id
        Result<UserDO> result = userFeignClient.getUserInfoByOpenId(openId);
        if (!result.getStatus()) {
            throw new BaseException("根据openId获取用户信息失败：" + openId);
        }
        redisUtil.hset(RedisKeyPrefix.ASSOCIATION_COUPON + openId, couponId.toString(), "1");
        if (result.getEntry() == null) {
            return Result.success();
        }
        UserDO userDO = result.getEntry();
        // 判断是否领取过
        LambdaQueryWrapper<CouponHistoryDO> queryWrapper = Wrappers.lambdaQuery(CouponHistoryDO.class)
                .eq(CouponHistoryDO::getUserId, userDO.getId())
                .eq(CouponHistoryDO::getCouponId, couponId);
        CouponHistoryDO couponHistoryDO = getOne(queryWrapper);
        if (couponHistoryDO != null) {
            return Result.fail("您已经领取过该优惠卷了！");
        }
        couponHistoryDO = new CouponHistoryDO();
        couponHistoryDO.setUserId(userDO.getId());
        couponHistoryDO.setGetType(1);
        couponHistoryDO.setCouponId(couponId);
        couponHistoryDO.setUseStatus(0);
        return this.save(couponHistoryDO) ? Result.success() : Result.fail();
    }

    @Override
    public Result sendReceiveAssociationCoupon(String openId, Long userId) {
        Map<Object, Object> hmget = redisUtil.hmget(RedisKeyPrefix.ASSOCIATION_COUPON + openId);
        if (CollectionUtils.isEmpty(hmget)) {
            return Result.success();
        }
        LambdaQueryWrapper<CouponHistoryDO> queryWrapper = Wrappers.lambdaQuery(CouponHistoryDO.class)
                .eq(CouponHistoryDO::getUserId, userId)
                .eq(CouponHistoryDO::getUseStatus, 0);
        List<CouponHistoryDO> list = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            batchAdd(userId, hmget);
            return Result.success();
        }
        for (CouponHistoryDO couponHistoryDO : list) {
            if (hmget.containsKey(couponHistoryDO.getCouponId().toString())) {
                hmget.remove(couponHistoryDO.getCouponId().toString());
            }
        }
        batchAdd(userId, hmget);
        redisUtil.del(RedisKeyPrefix.ASSOCIATION_COUPON + openId);
        return Result.success();
    }

    private void batchAdd(Long userId, Map<Object, Object> hmget) {
        List<CouponHistoryDO> couponHistorys = new ArrayList<>();
        hmget.forEach((k, v) -> {
            CouponHistoryDO couponHistoryDO = new CouponHistoryDO();
            couponHistoryDO.setUserId(userId);
            couponHistoryDO.setGetType(1);
            couponHistoryDO.setCouponId(Long.valueOf(String.valueOf(k)));
            couponHistoryDO.setUseStatus(0);
            couponHistorys.add(couponHistoryDO);
        });
        this.saveBatch(couponHistorys);
    }
}
